package com.zw.mes.module.tecard.service;

import com.zw.mes.entity.flow.FlowRoute;
import com.zw.mes.entity.flow.FlowSheet;
import com.zw.mes.entity.technology.Tecard;
import com.zw.mes.module.system.service.LogService;
import com.zw.mes.module.tecard.mapper.TecardMapper;
import com.zw.mes.module.tecard.repository.FlowDetialRepository;
import com.zw.mes.module.tecard.repository.FlowSheetRepository;
import com.zw.mes.util.ShiroUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;


import java.util.Date;
import java.util.List;

import static com.zw.mes.util.BeanUtil.getNullPropertyNames;


/**
 * @author mayongfeng
 * @version 1.0.0
 * @ClassName TecardService.java
 * @Description TODO
 * @createTime 2021年03月11日 10:28:00
 */
@Service
@SuppressWarnings("all")
public class TecardService {

    @Autowired
    private TecardMapper tecardMapper;
    @Autowired
    private FlowSheetRepository flowSheetRepository;
    @Autowired
    private FlowDetialRepository flowDetialRepository;
    @Autowired
    private LogService logService;
    /** 查询工艺卡接收列表页*/
    public List<Tecard> getCardRevice(Tecard tecard) {
        return tecardMapper.getCardRevice(tecard);
    }

    /** 查询项目下所有图号的工艺卡列表*/
    public List<Tecard> getMakeDetail(Tecard tecard) {
        List<Tecard> tecardList = new ArrayList<>();
        /** 判断工艺卡是否是变更的0=未变更,1=已变更*/
        if(tecard.getProdChange()==0){
            if(tecard.getRecStatus() == 0){
                tecardList = tecardMapper.getMakeDetail(tecard);
            }else{
                tecardList = tecardMapper.getMakeDetailOld(tecard);
            }
        }else if(tecard.getProdChange()==1){
            if(tecard.getRecStatus() == 0){
                tecardList = tecardMapper.getMakeDetailcha(tecard);
            }else{
                tecardList = tecardMapper.getMakeDetailOld(tecard);
            }
        }

        return tecardList;
    }

    /** 按主键查询主单 */
    public Tecard getCardById(Integer id) {
        return tecardMapper.getOne(id);
    }

    /** 查询图号的工艺卡明细 */
    public List<Tecard> findCardDetailByCardId(Integer id) {
        return tecardMapper.findByCardId(id);
    }

    /** 按主键查询生产工艺主单 */
    public Tecard getProdCardById(Integer id) {
        return tecardMapper.getProdCardById(id);
    }

    /** 查询生产图号的工艺卡明细 */
    public List<Tecard> findProdCardDetailByCardId(Integer id) {
        return tecardMapper.findProdCardDetailByCardId(id);
    }


    /**
     * @Author mayongfeng
     * @Date 15:19 2021/3/12
     * @Description 将pdm的工艺卡接收到生产系统里面来，修改工艺卡主表的接收状态
     *
     **/
    @Transactional(rollbackFor = Exception.class)
    public int cardReceive(Tecard tecard) {
        logService.saveLog("接收工艺卡", "工艺卡ID：" + tecard.getId());
        /** 接收人code*/
        tecard.setRecCode(ShiroUtils.getUser().getAccount());
        /** 接收人name*/
        tecard.setRecName(ShiroUtils.getUser().getName());
        /** 接收 0=未接收，1=已接收*/
        tecard.setRecStatus(1);
        /** 接收时间 */
        tecard.setRecTime(new Date());
        /** 通过Id修改主表的接收状态*/
        int i = tecardMapper.updateCardMakeSheet(tecard);
        if(i>0){
            int a = receiveCard(tecard);
            if(a>0){
                /** 通过生产令查询生产令表*/
                int prodExeSta = tecardMapper.findProdOrd(tecard);
                if(prodExeSta==0){
                    /** 修改生产令表里面的状态*/
                    tecardMapper.updateProdOrd(tecard.getProCode());
                }

            }

        }
        return i;
    }

    /**
     * @Author mayongfeng
     * @Date 8:55 2021/3/17
     * @Description 将技术文件的工艺卡接收到生产系统里面来
     *
     **/
    private int receiveCard(Tecard tecard) {
        int a = 0;
        /** 查询项目下有工艺卡的主单信息*/
        List<Tecard> craSheetList = tecardMapper.getSheetDetail(tecard);
        for (Tecard tecard1 : craSheetList) {
            if("加工件".equals(tecard1.getMakeType())){
                tecard1.setCategory(1);
            }else{
                tecard1.setCategory(2);
            }
                /** 接收人code*/
                tecard1.setRecCode(ShiroUtils.getUser().getAccount());
                /** 接收人name*/
                tecard1.setRecName(ShiroUtils.getUser().getName());
                /** 接收 0=未接收，1=已接收*/
                tecard1.setRecStatus(1);
                /** 接收时间 */
                tecard1.setRecTime(new Date());

            /** 根据变更标识判断时首次还是变更，0默认，1变更*/
            if(tecard1.getProdChange() == 0){
                logService.saveLog("接收正常的工艺卡", "工艺卡ID：" + tecard1.getId());

                a = addFirst(tecard1);

            }else if(tecard1.getProdChange()==1){
                logService.saveLog("接收变更的工艺卡", "工艺卡ID：" + tecard1.getId());

                FlowSheet flowSheet = new FlowSheet();
                /** 变更逻辑通过Id查询出生产工艺卡主表里面的数据*/
                FlowSheet flowSheetObj = tecardMapper.findFlowSheetId(tecard1.getId());
                if("".equals(flowSheetObj) || null == flowSheetObj){

                    a = addFirst(tecard1);

                }else{
                    copy(tecard1,flowSheet);
                    flowSheet.setId(flowSheetObj.getId());
                    flowSheet.setCraSheetId(flowSheetObj.getCraSheetId());
                    flowSheet.setProdNo(tecard1.getProCode());
                    flowSheet.setProNum(Integer.parseInt(tecard1.getProNum()));
                    flowSheet.setPartId(Integer.parseInt(tecard1.getPartId()));
                    flowSheet.setWeight(Double.parseDouble(tecard1.getWeight()));
                    flowSheet.setCreateCode(tecard1.getCreateCodeOne());
                    flowSheet.setCreateName(tecard1.getCreateNameOne());
                    flowSheet.setCheckCode(tecard1.getVerifyCode());
                    flowSheet.setCheckName(tecard1.getVerifyName());
                    flowSheet.setCheckTime(tecard1.getVerifyTime());
                    flowSheet.setInvalid(flowSheetObj.getInvalid());
                    /** 通过ID修改主单信息*/
                    flowSheetRepository.save(flowSheet);
                    /** 根据主表Id先删除生产工艺卡从表的数据*/
                    Integer i  = tecardMapper.deleteFlowDetail(flowSheetObj.getId());
                    /** 通过Id查询技术文件工艺卡明细表里面的明细集合*/
                    List<Tecard> byCardId = tecardMapper.findByCardId(tecard1.getId());
                    for (Tecard craPlan : byCardId) {
                        craPlan.setCardId(flowSheetObj.getId());
                        tecardMapper.addCarFlowDetail(craPlan);
                    }
                    int notRouteNum=0;
                    /** 修改技术文件工艺卡主表里面的的接收状态*/
                    a =  tecardMapper.updateCarSheet(tecard1);
                    /** 变更后的查询从表去重明细*/
                    List<Tecard> newList = byCardId.stream().filter(distinctByKey(Tecard::getOrderNo)).collect(Collectors.toList());

                    /** 通过Id查询flowRoute路线明细*/
                    List<FlowRoute> flowRoutes = tecardMapper.findFlowRoutes(flowSheet.getId());
                    for (FlowRoute flowRoute : flowRoutes) {
                        /** 已接收数量为0的数据可以删除*/
                        if(flowRoute.getRecNum()==0){
                            int routeNum = tecardMapper.deleteFlowRoutes(flowRoute.getId());
                        }else{
                            notRouteNum++;
                        }
                    }
                    /** 将不能修改的数据删除掉*/
                    for (int i1 = 0; i1 < notRouteNum; i1++) {
                        newList.remove(0);
                    }

                    if(newList.size()>0){
                        for (Tecard route1 : newList) {
                            route1.setCardId(flowSheetObj.getId());
                            tecardMapper.addCarFlowRoute(route1);
                        }
                    }

                }

            }


        }
        return a;
    }

    /**
     * @Author mayongfeng
     * @Date 14:23 2021/3/23
     * @Description 首次接收添加,或者变更后的首次接收都走这一个方法.
     *
     **/
    private int addFirst(Tecard tecard1) {
        int a;
        /** 通过Id查询工艺卡明细表里面的明细集合*/
        List<Tecard> byCardId = tecardMapper.findByCardId(tecard1.getId());
        /** 查去重明细*/
        List<Tecard> newList = byCardId.stream().filter(distinctByKey(Tecard::getOrderNo)).collect(Collectors.toList());

        /** 修改技术文件工艺卡主表里面的的接收状态*/
        a =  tecardMapper.updateCarSheet(tecard1);

        /** 将技术文件的工艺卡主表保存到生产工艺卡主表*/
        tecardMapper.addCarSheet(tecard1);
        /** 将明细表里的数据添加到生产工艺卡的明细表里面*/
        for (Tecard craPlan : byCardId) {
            craPlan.setCardId(tecard1.getId());
            tecardMapper.addCarFlowDetail(craPlan);
        }
        /** 将明细表里面的路线根据路线编号去重添加到生产工艺路线表里面*/
        for (Tecard route1 : newList) {
            route1.setCardId(tecard1.getId());
            tecardMapper.addCarFlowRoute(route1);
        }
        return a;
    }

    /**List集合根据对象某个属性去重*/
    private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    /** 打印工艺卡列表 */
    public List<FlowSheet> findWithCardQuery(Tecard tecard) {

        return tecardMapper.findWithCardQuery(tecard);
    }

    /** 批量打印工艺卡*/
    public List<Tecard> findCardListFull(Integer[] ids) {
        logService.saveLog("批量打印生产的工艺的卡", "工艺卡ID：" + ids);

        List<Tecard> byIds = tecardMapper.findByIds(ids);
        for (Tecard byId : byIds) {
            if(byId.getCreateTel()==null || "".equals(byId.getCreateTel())){
                String createTel = tecardMapper.findCreateTel(byId.getCreateCode());
                byId.setCreateTel(createTel);
            }
        }
        return byIds;
    }

    /**
     * 复制对象，并排除空值属性
     *
     * @param source 源对象
     * @param target 目标对象
     */
    public static void copy(Object source, Object target) {
        BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
    }


}
